package com.hyt.it.ogt.kq.service.gov.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hyt.it.ogt.kq.service.gov.model.vo.ArrangeCountVo;
import com.hyt.it.ogt.kq.service.gov.model.vo.arrange.ArrangeCount;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Maps;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.StringUtils;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.common.gov.constant.CodeEnum;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.service.gov.mapper.CandidateSubjectMapper;
import com.hyt.it.ogt.kq.service.gov.model.dto.arrange.CandidateSubjectDTO;
import com.hyt.it.ogt.kq.service.gov.model.entity.Task;
import com.hyt.it.ogt.kq.service.gov.model.vo.CandidateArrangePreVO;
import com.hyt.it.ogt.kq.service.gov.model.vo.CandidateArrangeSubjectPreVO;
import com.hyt.it.ogt.kq.service.gov.model.vo.CandidateSubjectVO;
import com.hyt.it.ogt.kq.service.gov.service.ICandidateService;
import com.hyt.it.ogt.kq.service.gov.service.ICandidateSubjectService;
import com.hyt.it.ogt.kq.service.gov.service.ISubjectService;
import com.hyt.it.ogt.kq.service.gov.service.ITaskService;
import com.hyt.it.ogt.kq.service.model.entity.Candidate;
import com.hyt.it.ogt.kq.service.model.entity.CandidateSubject;
import com.hyt.it.ogt.kq.service.model.entity.Subject;
import com.hyt.it.ogt.kq.service.model.param.PushCandidateSubjectParam;

import cn.hutool.core.collection.CollUtil;

/**
 * <p>
 * 考生科目中间表 服务实现类
 * </p>
 *
 * @author huangyh
 * @since 2021-04-07
 */
@Service
public class CandidateSubjectServiceImpl extends BaseServiceImpl<CandidateSubjectMapper, CandidateSubject> implements ICandidateSubjectService {

    @Resource
    private ICandidateService iCandidateService;

    @Resource
    private ISubjectService iSubjectService;

    @Resource
    private ITaskService iTaskService;

    @Override
    public void deleteCandidateSubjects(String taskId, List<String> candidateIdList) {
        QueryWrapper<CandidateSubject> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(CandidateSubject::getTaskId, taskId)
                .in(CollectionUtils.isNotEmpty(candidateIdList), CandidateSubject::getCandidateId, candidateIdList)
                .eq(CandidateSubject::getDelFlag, false);
        this.remove(queryWrapper);
        //return baseMapper.deleteByCandidateIds(candidateIds);
    }

    @Override
    public int selectNoTimeRoomCandidateCount(String taskId) {
        return baseMapper.selectNoTimeRoomCandidateCount(taskId);
    }

    @Override
    public List<String> getCandidateSubjectNames(String candidateId) {
        return baseMapper.getCandidateSubjectNames(candidateId);
    }

    @Override
    public List<Subject> existBySubjects(Set<String> subjectCodes, String taskId) {
        return baseMapper.existBySubjects(subjectCodes,taskId);
    }

    @Override
    public List<CandidateSubject> listByTaskId(String taskId) {
        QueryWrapper<CandidateSubject> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(CandidateSubject::getTaskId, taskId)
                .eq(CandidateSubject::getDelFlag, false);
        return list(queryWrapper);
    }

    @Override
    public boolean insertSubjects(List<CandidateSubject> candidateSubjects) {
        return baseMapper.insertSubjects(candidateSubjects) > 0;
    }

    @Override
    public Map<String, CandidateArrangePreVO> getCandidateNeedArrange(String taskId) {
        List<CandidateSubjectVO> candidateSubjectVOList = baseMapper.selectNoArrangeCandidate(taskId);
        if (candidateSubjectVOList == null || candidateSubjectVOList.isEmpty()) {
            //没有未编排的考生
            throw new KqException(ResponseCode.ARRANGE_CANDIDATE_NOT_FOUND.getCode(),ResponseCode.ARRANGE_CANDIDATE_NOT_FOUND.getMsg());
        }

        //candidateId，省，市，县区，考点
        //科目list
        //科目考试类型list
        Map<String, CandidateArrangePreVO> candidateMap = Maps.newHashMap();
        candidateSubjectVOList.stream().forEach(candidateSubjectVO -> {
            String candidateId = candidateSubjectVO.getCandidateId();
            CandidateArrangePreVO candidateArrangePreVO = null;
            if (candidateMap.containsKey(candidateId)) {
                candidateArrangePreVO = candidateMap.get(candidateId);
            } else {
                candidateArrangePreVO = new CandidateArrangePreVO();
                candidateArrangePreVO.setCandidateId(candidateSubjectVO.getCandidateId())
                        .setProvince(candidateSubjectVO.getProvince())
                        .setCity(candidateSubjectVO.getCity())
                        .setDistrict(candidateSubjectVO.getDistrict())
                        .setPlaceId(candidateSubjectVO.getPlaceId());
            }

            CandidateArrangeSubjectPreVO subjectPreVO = new CandidateArrangeSubjectPreVO();
            subjectPreVO.setSubjectId(candidateSubjectVO.getSubjectId())
                    .setAnswerType(candidateSubjectVO.getAnswerType())
                    .setCandidateSubjectId(candidateSubjectVO.getId());

            List<CandidateArrangeSubjectPreVO> candidateArrangeSubjectPreVOList = candidateArrangePreVO.getCandidateArrangeSubjectPreVOList();
            if (candidateArrangeSubjectPreVOList == null || candidateArrangeSubjectPreVOList.isEmpty()) {
                candidateArrangeSubjectPreVOList = new ArrayList<CandidateArrangeSubjectPreVO>();
            }
            candidateArrangeSubjectPreVOList.add(subjectPreVO);

            candidateArrangePreVO.setCandidateArrangeSubjectPreVOList(candidateArrangeSubjectPreVOList);

            candidateMap.put(candidateId,candidateArrangePreVO);
        });

        return candidateMap;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void insertByPushCandidateSubjectParam(PushCandidateSubjectParam param, Subject subject) {
        if (CollUtil.isEmpty(param.getCandidateIdList())) {
            return;
        }
        List<CandidateSubject> candidateSubjects = new ArrayList<>();
        param.getCandidateIdList().stream().forEach(candidateId -> {
            CandidateSubject candidateSubject = new CandidateSubject();
            Candidate candidate = iCandidateService.getCandidateByBmStudentId(param.getTaskId(), candidateId);
            if (candidate != null ) {
                candidateSubject.setCandidateId(candidate.getId())
                        .setAnswerType(CodeEnum.COMPUTER_EXAM.getCode())
                        .setSubjectId(subject.getId())
                        .setLanguage(1)
                        .setTaskId(param.getTaskId())
                        .setId(UUIDUtils.newSortUUID());
                candidateSubjects.add(candidateSubject);
            }
        });
        this.saveBatch(candidateSubjects);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void deleteByPushCandidateSubjectParam(PushCandidateSubjectParam param, String subjectId) {
        if (CollUtil.isEmpty(param.getCandidateIdList())) {
            return;
        }
        List<Candidate> candidates = iCandidateService.lambdaQuery()
                .eq(Candidate::getTaskId,param.getTaskId())
                .eq(Candidate::getDelFlag,false)
                .in(Candidate::getBmStudentId,param.getCandidateIdList())
                .select(Candidate::getId)
                .list();
        if (CollUtil.isEmpty(candidates)) {
            return ;
        }
        List<String> candidateIdList = new ArrayList<>();
        candidates.stream().forEach(candidate -> {
            candidateIdList.add(candidate.getId());
        });

        this.lambdaUpdate()
                .eq(CandidateSubject::getTaskId,param.getTaskId())
                .eq(CandidateSubject::getSubjectId,subjectId)
                .eq(CandidateSubject::getDelFlag,false)
                .in(CandidateSubject::getCandidateId,candidateIdList)
                .set(CandidateSubject::getDelFlag,true)
                .update();
    }

    /**
     * 科目数据校验-并且更新和补全科目code和考生身份证号
     * @param taskId 考试任务id
     * @throws KqException 异常
     */
    @Override
    public void checkCandidateSubjectUpdateSubjectCodeOrIdNumber(String taskId) throws KqException {

        if (!CodeEnum.TASK_DATA_TYPE_BM.getCode().equals(iTaskService.taskDataType(taskId))) {
            return;
        }

        //1.校验是否存在科目编号
        List<Subject> subjectList = iSubjectService.getIdCode(taskId);
        if (CollectionUtils.isEmpty(subjectList)) {
            //暂无科目数据
            throw new KqException(ResponseCode.ARRANGE_SUBJECT_NOT_FOUND.getCode(),ResponseCode.ARRANGE_SUBJECT_NOT_FOUND.getMsg());
        }
    }

    @Override
    public void checkCandidateSubjectUpdateSubjectCodeOrIdNumber(Task task) throws KqException {

        if (!CodeEnum.TASK_DATA_TYPE_BM.getCode().equals(iTaskService.taskDataType(task))) {
            return;
        }

        //1.校验是否存在科目编号
        List<Subject> subjectList = iSubjectService.getIdCode(task.getId());
        if (CollectionUtils.isEmpty(subjectList)) {
            //暂无科目数据
            throw new KqException(ResponseCode.ARRANGE_SUBJECT_NOT_FOUND.getCode(),ResponseCode.ARRANGE_SUBJECT_NOT_FOUND.getMsg());
        }
    }

    @Override
    public List<CandidateSubjectDTO> getCandidateSubjectDTO(String taskId) {
        return baseMapper.getCandidateSubjectDTO(taskId);
    }

    @Override
    public List<CandidateSubjectDTO> getNoArrangeCandidateByOnLine(String taskId) {
        return baseMapper.selectNoArrangeCandidateByOnLine(taskId);
    }

    @Override
    public boolean hasCandidateSubject(String taskId, String candidateId, String subjectId) {
        return this.lambdaQuery().select(CandidateSubject::getId)
                .eq(CandidateSubject::getTaskId, taskId)
                .eq(CandidateSubject::getCandidateId, candidateId)
                .eq(CandidateSubject::getSubjectId, subjectId)
                .eq(CandidateSubject::getDelFlag, false)
                .last("LIMIT 1")
                .oneOpt()
                .isPresent();
    }

    @Override
    public CandidateSubject one(String taskId, String candidateId, String subjectId) {
        return this.lambdaQuery()
                .eq(CandidateSubject::getTaskId, taskId)
                .eq(CandidateSubject::getCandidateId, candidateId)
                .eq(CandidateSubject::getSubjectId, subjectId)
                .eq(CandidateSubject::getDelFlag, false)
                .last("LIMIT 1")
                .one();
    }

    @Override
    public boolean hasCandidateSubject(String taskId, String subjectId) {
        return this.lambdaQuery().select(CandidateSubject::getId)
                .eq(CandidateSubject::getTaskId, taskId)
                .eq(CandidateSubject::getSubjectId, subjectId)
                .eq(CandidateSubject::getDelFlag, false)
                .last("LIMIT 1")
                .oneOpt()
                .isPresent();
    }

    /**
     * 通过考生id查询考务下考生科目一些字段：subjectId answerType candidateId subjectName
     *
     * @param candidateIds 考生id
     * @param taskId 考务id
     * @return 考生科目
     */
    @Override
    public List<CandidateSubjectDTO> getByCandidateIdsAndTaskId(List<String> candidateIds, String taskId) {
        if (StringUtils.isEmpty(taskId) || candidateIds.isEmpty()) {
            return Collections.emptyList();
        }
        return baseMapper.getByCandidateIdsAndTaskId(candidateIds, taskId);

    }

    @Override
    public List<ArrangeCount> getSubjectCandidateCount(String taskId) {
        return baseMapper.getSubjectCandidateCount(taskId);
    }

    @Override
    public List<ArrangeCountVo> getCountBySubject(String taskId){
        return baseMapper.getCountBySubject(taskId);
    }
}
